﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YasharEl.Infrastructure.ExceptionHandling
{
    public abstract class BaseExceptionManager : IExceptionManager
    {
        #region IExceptionManager Implementations

        public bool HandleException(Exception exceptionToHandle, string policyName, out Exception exceptionToThrow)
        {
            try
            {
                bool shouldRethrow = HandleException(exceptionToHandle, policyName);
                exceptionToThrow = null;

                return shouldRethrow;
            }
            catch (Exception exception)
            {
                exceptionToThrow = exception;
                return true;
            }
        }

        public bool HandleException(Exception exceptionToHandle, string policyName)
        {
            IExceptionPolicy exceptionPolicy;

            if (!GetExceptionPolicy(policyName, out exceptionPolicy))
            {
                string message = string.Format("The policy with name '{0}' cannot be found. Exception handling aborted.", policyName);

                throw new ExceptionHandlingException(message);
            }

            return exceptionPolicy.HandleException(exceptionToHandle);
        }

        public void Process(Action action, string policyName)
        {
            try
            {
                action();
            }
            catch (Exception e)
            {
                if (HandleException(e, policyName))
                {
                    throw;
                }
            }
        }

        public TResult Process<TResult>(Func<TResult> action, TResult defaultResult, string policyName)
        {
            try
            {
                return action();
            }
            catch (Exception e)
            {
                if (HandleException(e, policyName))
                {
                    throw;
                }
            }
            return defaultResult;
        }

        #endregion

        #region Abstract Methods

        protected abstract bool GetExceptionPolicy(string policyName, out IExceptionPolicy exceptionPolicy);

        #endregion
    }
}
